/*jslint vars:true plusplus:true*/

//=========================================================
// Interactive Digital Media Diploma
// CUFDIG404A_R1: Introduction to Scripting
// Assignment 3
// Author: Ben
// File: collider.js
// Description: Simple collision system
//=========================================================


// collider tracks collisions
function Collider(entity, radius, layer, offsetX, offsetY, onHit) {
    "use strict";
    var self = this;
    var ent = entity;
    self.radius = radius;
    self.layer = layer;
    self.isHit = false;
    self.isEnabled = true;
    self.getX = function () { return ent.x + offsetX; };
    self.getY = function () { return ent.y + offsetY; };
    self.onHit = onHit;
    
    // respond to hit
    this.hit = function (otherCollider) {
        if (entity.hit !== undefined) {
            entity.hit(otherCollider.layer);
        }
        if (onHit !== undefined) {
            onHit(self, otherCollider.layer, otherCollider);
        }
        self.isHit = true;
    };
    
    // draw the collider
    this.debugdraw = function (context) {
        context.moveTo(entity.x + offsetX + self.radius, entity.y + offsetY);
        context.arc(entity.x + offsetX, entity.y + offsetY, self.radius, 0, 2 * Math.PI);
        context.moveTo(entity.x - 2, entity.y - 2);
        context.rect(entity.x - 2, entity.y - 2, 4, 4);
    };
    
    window.game.collision.addCollider(self);
}


// 
// tracks all of the collision in the game
function Collision() {
    "use strict";
    var self = this;
    this.isVisible = false;
    
    // a list of possible colliders
    var colliders = [];

    
    // add a new collider to the game
    this.addCollider = function (collider) {
        colliders.push(collider);
    };

    
    // draw the collider - used for debugging
    this.debugdraw = function (context) {
        var idx;
        if (self.isVisible) {
                
            // draw all non-hit collision
            context.beginPath();
            for (idx = 0; idx < colliders.length; idx++) {
                if (!colliders[idx].isHit) {
                    colliders[idx].debugdraw(context);
                }
            }
            context.lineWidth = 2;
            context.strokeStyle = 'black';
            context.stroke();

            // draw all hit collision
            context.beginPath();
            for (idx = 0; idx < colliders.length; idx++) {
                if (colliders[idx].isHit) {
                    colliders[idx].debugdraw(context);
                }
            }
            context.lineWidth = 4;
            context.strokeStyle = 'red';
            context.stroke();
        }
    };
    
    
    // update all of the collision using simple circluar collision fields
    this.update = function () {
        var offsetX, offsetY;
        var minOffset;
        var i, j;
        var colliderI, colliderJ;

        for (i = 0; i < colliders.length; i++) {
            colliders[i].isHit = false;
        }
        
        // compare all colliders
        for (i = 0; i < colliders.length; i++) {
            colliderI = colliders[i];
            if (colliderI.isEnabled) {
                for (j = i + 1; j < colliders.length; j++) {
                    colliderJ = colliders[j];
                    if (colliderJ.isEnabled) {
                        // if we're not on the same layer
                        if (colliderI.layer !== colliderJ.layer) {
                            // the radius of the two circles - the points must be at least this 
                            // far apart for the circles not to overlap
                            minOffset = colliderI.radius + colliderJ.radius;

                            // the horizontal offset of the two circles
                            offsetX = colliderI.getX() - colliderJ.getX();

                            // the vertical offset of the two circles
                            offsetY = colliderI.getY() - colliderJ.getY();

                            // pythagorean theorem - if true, then circles overlap. 
                            if (offsetX * offsetX + offsetY * offsetY < minOffset * minOffset) {
                                colliderI.hit(colliderJ);
                                colliderJ.hit(colliderI);
                            }
                        }
                    }
                }
            }
        }
        
    };
}

// accessible as a game member
window.game.collision = new Collision();

// add game subsystem
window.game.addSubsystem(window.game.collision);